<?php
/**
 * Base class for all models
 *
 * @author longpt
 * @version
 */
require_once 'Zend/Db/Table/Abstract.php';
require_once 'configs/Config.php';
require_once 'DBUtils.php';
require_once 'IBaseModel.php';
require_once 'DataCache.php';

abstract class BaseModel extends Zend_Db_Table_Abstract {

	protected $lastInsertID = null;
	
	protected $_names = 'default';

	protected $_primary = 'id';

	protected $_data;

	protected $id;

	protected $cache;

	public function getCache() {
		return $this->cache;
	}

	public function getId() {
		return $this->id;
	}

	public function setId($id) {
		$this->id = $id;
	}

	public function __construct($id, $needQuery = true) {
		parent::__construct ();
		$this->cache = new DataCache ();
		$this->id = $id;
		if ($needQuery) {
			if ($id) {
				$this->load ( $id );
			} else {
				$this->_data = $this->createDefaultData ();
			}
		}
	}

	/**
	 * Override the base class to setup a custom database adapter
	 * (non-PHPdoc)
	 * @see library/Zend/Db/Table/Zend_Db_Table_Abstract::_setupDatabaseAdapter()
	 */
	public function _setupDatabaseAdapter() {
		$this->_db = DBUtils::createDatabaseAdapter ();
		parent::_setupDatabaseAdapter ();
	}

	public function createDefaultData() {}

	public function abstractLoad($id) {}

	public function load($id) {
		$this->abstractLoad ( $id );
	}

	/**
	 * Change the property of this profile based on its name
	 * @param string $propName
	 * @param string $propValue
	 * @return false if this profile doesn't have that property
	 */
	public function setProp($propName, $propValue) {
		if ($this->_data !== null)
			$this->_data [$propName] = $propValue;
		else
			return false;
	}

	/**
	 * Find a property from cache
	 * @param unknown_type $propName
	 */
	public function findFromCache($propName) {
		return $this->cache
			->find ( 'properties', $propName );
	}

	public function findWithoutCache($propName) {
		return $this->getProp ( $propName );
	}

	public function getProp($propName) {
		if ($this->isDataSet () && array_key_exists ( $propName, $this->_data ))
			return $this->_data [$propName];
		return null;
	}

	public function __set($propName, $propValue) {
		$this->setProp ( $propName, $propValue );
		$this->getCache ()
			->update ( 'properties', $propName, $propValue );
	}

	public function __get($propName) {
		$cached = $this->findFromCache ( $propName );
		if ($cached == null) {
			//cache miss
			$cached = $this->findWithoutCache ( $propName );
			if ($cached != null) {
				//update the cache
				$this->cache
					->update ( 'properties', $propName, $cached );
			}
		}
		return $cached;
	}

	public function setData($arr) {
		//we should clear the cache because the data have changed
		$this->cache
			->clear ();
		$this->_data = $arr;
	}

	public function getData() {
		return $this->_data;
	}
	
	public function buildWhere()	{
		$where = array ();
		foreach ( $this->_primary as $value ) {
			$where [] = $value . "='" . $this->_data[$value] . "'";
		}
		return $where;
	}

	/**
	 * Update the current row
	 * (non-PHPdoc)
	 * @see application/models/IBaseModel::updateRow()
	 */
	public function updateRow() {
		$where = $this->buildWhere();
		return $this->update ( $this->_data, $where );
	}
	
	public function deleteRow()	{
		$where = $this->buildWhere();
		return $this->delete($where);
	}
	
	/**
	 * 
	 * Insert row with custom data
	 * @param unknown_type $data
	 */
	public function insertRowWithData($data) {
		try {
			$this->lastInsertID = $this->insert ( $data );
		} catch ( Exception $ex ) {
			return false;
		}
		return true;
	}
	
	public function getLastInsertID()	{
		return $this->lastInsertID;
	}

	/**
	 * Insert current data to the DB
	 * (non-PHPdoc)
	 * @see application/models/IBaseModel::insertRow()
	 */
	public function insertRow() {
		return $this->insertRowWithData ( $this->_data );
	}

	/**
	 * 
	 * Check if the data has been initialized
	 */
	public function isDataSet() {
		if ($this->_data == null)
			return false;
		return true;
	}

	public function clean($uncleaned) {
		$cleaned = $this->quote ( $uncleaned );
		$cleaned = trim ( $cleaned, "'" );
		$cleaned = rtrim ( $cleaned, "'" );
		return $cleaned;
	}
	
	public function quote($value) {
		return $this->_db->quote ( $value );
	}

	public function countTotal()	{
		$stmt = $this->select()->from($this->_name, array('total'=>'count(id)'));
		$result = $this->fetchRow($stmt);
		if ($result == null)
			return 0;
		return $result->total;
	}
	public function exist($columns,$values){
		$stmt = $this->select();
		$bind = array();
		for($i=0;$i<count($columns);$i++){
			$stmt = $stmt->where("$columns[$i] = :_item$i");
			$bind[":_item$i"] = $values[$i];
		}
		$stmt->bind($bind);
		$result = $this->fetchRow($stmt);
		if ($result)
		{
			return true;
		}
		return false;
	}
}